package rensoft.portfolio.client.view.viewer;

import static com.google.gwt.query.client.GQuery.$;
import static com.google.gwt.query.client.GQuery.$$;

import com.google.gwt.core.client.GWT;
import com.google.gwt.query.client.Function;
import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;

import static cs.java.lang.Lang.doLater;
import static cs.java.lang.Lang.is;

import cs.java.lang.HasService;
import cs.java.lang.Run;



import static rensoft.gwt.client.lang.GwtLang.hideAll;
import static rensoft.gwt.client.lang.GwtLang.setFadeVisible;

import rensoft.gwt.client.event.EventFunction;
import rensoft.gwt.client.view.View;
import rensoft.portfolio.client.lib.view.LinkButton;
import rensoft.portfolio.client.model.titles.Page;
import rensoft.portfolio.client.model.titles.Title;
import rensoft.portfolio.client.model.titles.Titles;
import rensoft.portfolio.client.model.titles.Titles.TitleState;
import rensoft.portfolio.client.view.pages.ContactViewProvider;
import rensoft.portfolio.client.view.pages.PageViewProvider;

public class ViewerWidget extends View<IsWidget> {

  static Binder uiBinder = GWT.create(Binder.class);

  @UiField
  LinkButton backButton;
  @UiField
  CloseHandle closeHandle;
  @UiField
  LinkButton nextButton;
  @UiField
  HTML pageNumberInfo;
  @UiField
  PageViewer viewer;
  private boolean opened;
  Titles titles;

  public ViewerWidget() {
    initWidget(uiBinder.createAndBindUi(this));
    hide();
  }

  @Override
  public void initialize(HasService parent) {
    super.initialize(parent);
    viewer.initialize(this);
    closeHandle.initialize(this);
    titles = get(Titles.class);
    titles.addHandler(Titles.ON_CHANGE, new EventFunction<Title>() {
      public void run(Title value) {
        onTitleChange();
      }
    });
    onTitleChange();
  }

  @Override
  protected void hide() {
    hideAll(viewer, nextButton, backButton, pageNumberInfo);
    setHeight(0);
    super.hide();
  }

  private void animateWidget(final String properties, final Function... function) {
    doLater(new Run() {
      public void run() {
        $(asWidget()).animate($$(properties), NORMAL_ANIMATION, Easing.SWING, function);
      }
    });
  }

  private void close() {
    $(asWidget()).animate($$("height:'-=" + getHeight() + "'"), QUICK_ANIMATION, Easing.SWING,
        new Function() {
          @Override
          public void f() {
            viewer.close();
            hide();
          }
        });
    opened = false;
    updateControlsVisibility();
  }

  private String createPageInfoHtml() {
    String pageTitle = "<div style='font-size: medium;position: relative;'>page</div>";
    String ofTitle = " <span style='font-size: medium;'>of</span> ";
    return pageTitle + (getTitle().getCurrentIndex() + 1) + ofTitle + getTitle().getPageCount();
  }

  private Title getTitle() {
    return titles.getOpenTitle();
  }

  private boolean hasPages() {
    return getTitle().getPageCount() > 1;
  }

  private boolean isBackVisible() {
    return getTitle().getCurrentIndex() > 0;
  }

  private boolean isNextVisible() {
    return getTitle().getPageCount() > getTitle().getCurrentIndex() + 1;
  }

  private void onPageChange() {
    updateHeight();
    if (isNextVisible())
      nextButton.setTarget(getTitle().getPage(getTitle().getCurrentIndex() + 1).getId());
    if (isBackVisible())
      backButton.setTarget(getTitle().getPage(getTitle().getCurrentIndex() - 1).getId());
    if (hasPages()) pageNumberInfo.setHTML(createPageInfoHtml());
    updateControlsVisibility();
  }

  private void onTitleChange() {
    if (is(getTitle())) {
      registerReplace(getTitle(), Title.ON_PAGE_CHANGE, new EventFunction<Page>() {
        public void run(Page value) {
          onPageChange();
        }
      });
      if (getTitle().getType() == TitleState.contact)
        viewer.show(new ContactViewProvider(getTitle()));
      else viewer.show(new PageViewProvider(getTitle()));
      opened = true;
      onPageChange();
    } else {
      unregister(Title.ON_PAGE_CHANGE);
      if (opened) close();
    }
  }

  private void updateControlsVisibility() {
    setFadeVisible(opened, viewer);
    setFadeVisible(opened && isNextVisible(), nextButton);
    setFadeVisible(opened && isBackVisible(), backButton);
    setFadeVisible(opened && hasPages(), pageNumberInfo);
  }

  private void updateHeight() {
    if (getHeight() < getTitle().getPage().getHeight())
      animateWidget("height:'+=" + (getTitle().getPage().getHeight() - getHeight()) + "'");
    else animateWidget("height:'-=" + (getHeight() - getTitle().getPage().getHeight()) + "'");
  }

  interface Binder extends UiBinder<Widget, ViewerWidget> {}

}
